package genCodeUtil.genRealize;


import com.google.common.base.CaseFormat;
import freemarker.template.Configuration;
import freemarker.template.TemplateExceptionHandler;
import genCodeUtil.genConfig.Column;
import genCodeUtil.genConfig.DatabaseUtil;
import genCodeUtil.genConfig.GenConfig;
import org.mybatis.generator.config.*;
import org.mybatis.generator.plugins.SerializablePlugin;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author : Simon
 * @date : 2020/4/7
 */
public class BaseInit {

    GenConfig config = new GenConfig();

    /**
     * Freemarker 模板环境配置
     *
     * @return
     * @throws IOException
     */
    public Configuration initFreemarkerConfiguration(String templateDir) {
        Configuration cfg = null;
        try {
            cfg = new Configuration(Configuration.VERSION_2_3_23);
            cfg.setDirectoryForTemplateLoading(new File(templateDir));
            cfg.setDefaultEncoding("UTF-8");
            cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
        } catch (Exception e) {
            throw new RuntimeException("Freemarker 模板环境初始化异常!", e);
        }
        return cfg;
    }

    /**
     * 功能描述:
     * 〈根据模板名称获取后缀名〉
     *
     * @Author: Simon
     * @Date: 2020/4/7 9:59
     */
    public String getSuffixByTemplateName(String templateName) {
        String suffix = "";
        switch (templateName) {
            case "managerGen.ftl":
                suffix = "Manager.java";
                break;
            case "controllerGen.ftl":
                suffix = "Controller.java";
                break;
            case "serviceGen.ftl":
                suffix = "Service.java";
                break;
            case "serviceImplGen.ftl":
                suffix = "ServiceImpl.java";
                break;
            default:
                suffix = "";
        }
        return suffix;
    }

    /**
     * 功能描述:
     * 〈根据模板名称获取目标目录地址〉
     *
     * @Author: Simon
     * @Date: 2020/4/7 10:33
     */
    public String getTargetByTemplateName(String templateName) {
        String target = "";
        switch (templateName) {
            case "managerGen.ftl":
                target = GenConfig.MANAGER_PATH;
                break;
            case "controllerGen.ftl":
                target = GenConfig.CONTROLLER_PATH;
                break;
            case "serviceGen.ftl":
                target = GenConfig.SERVICE_PATH;
                break;
            case "serviceImplGen.ftl":
                target = GenConfig.SERVICE_IMPL_PATH;
                break;
            default:
                target = "";
        }
        return target;
    }

    /**
     * 完善初始化环境
     *
     * @param tableName 表名
     * @param modelName 自定义实体类名, 为null则默认将表名下划线转成大驼峰形式
     */
    public Context initConfig(String tableName, String modelName) {
        Context context = null;
        try {
            context = initMybatisGeneratorContext();
            JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration();
            javaModelGeneratorConfiguration.setTargetProject(GenConfig.PROJECT_PATH + GenConfig.JAVA_PATH);
            javaModelGeneratorConfiguration.setTargetPackage(GenConfig.MODEL_PACKAGE_PATH);
            context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration);

            JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration();
            javaClientGeneratorConfiguration.setTargetProject(GenConfig.PROJECT_PATH + GenConfig.JAVA_PATH);
            javaClientGeneratorConfiguration.setTargetPackage(GenConfig.MAPPER_PACKAGE_PATH);
            javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER");
            context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration);

            TableConfiguration tableConfiguration = new TableConfiguration(context);
            tableConfiguration.setTableName(tableName);
            tableConfiguration.setDomainObjectName(modelName);
//            tableConfiguration.setGeneratedKey(new GeneratedKey("id", "Mysql", true, null));
            context.addTableConfiguration(tableConfiguration);
        } catch (Exception e) {
            throw new RuntimeException("ModelAndMapperGenerator 初始化环境异常!", e);
        }
        return context;
    }


    /**
     * Mybatis 代码自动生成基本配置
     *
     * @return
     */
    public Context initMybatisGeneratorContext() {
        Context context = new Context(ModelType.FLAT);
        context.setId("Mysql");
        context.setTargetRuntime("MyBatis3Simple");
        context.addProperty(PropertyRegistry.CONTEXT_BEGINNING_DELIMITER, "`");
        context.addProperty(PropertyRegistry.CONTEXT_ENDING_DELIMITER, "`");
        context.addProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING, "UTF-8");

        JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration();
        jdbcConnectionConfiguration.setConnectionURL(GenConfig.JDBC_URL);
        jdbcConnectionConfiguration.setUserId(GenConfig.JDBC_USERNAME);
        jdbcConnectionConfiguration.setPassword(GenConfig.JDBC_PASSWORD);
        jdbcConnectionConfiguration.setDriverClass(GenConfig.JDBC_DRIVER_CLASS_NAME);
        jdbcConnectionConfiguration.addProperty("useInformationSchema", "true");
        context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration);

        SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration();
        sqlMapGeneratorConfiguration.setTargetProject(GenConfig.PROJECT_PATH + GenConfig.RESOURCES_PATH);
        sqlMapGeneratorConfiguration.setTargetPackage(GenConfig.XML_PACKAGE_PATH);
        context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration);

        // 增加 mapper 插件
        addMapperPlugin(context);
        //java序列化
        addSerializablePlugin(context);

        return context;
    }

    /**
     * 增加插件
     */
    private void addMapperPlugin(Context context) {
        PluginConfiguration pluginConfiguration = new PluginConfiguration();
        pluginConfiguration.setConfigurationType("tk.mybatis.mapper.generator.MapperPlugin");
        pluginConfiguration.addProperty("mappers", GenConfig.MAPPER_INTERFACE_REFERENCE);
        pluginConfiguration.addProperty("swagger", "true");
        pluginConfiguration.addProperty("lombok", "Data");
        pluginConfiguration.addProperty("forceAnnotation", "true");
        context.addPluginConfiguration(pluginConfiguration);
    }

    /**
     * 增加序列化plugin
     * @param context
     */
    private void addSerializablePlugin(Context context){
        PluginConfiguration pluginConfiguration = new PluginConfiguration();
        pluginConfiguration.setConfigurationType("org.mybatis.generator.plugins.SerializablePlugin");
        context.addPluginConfiguration(pluginConfiguration);
    }

    /**
     * 下划线转成驼峰, 首字符为大写
     * eg: gen_test_demo ==> GenTestDemo
     *
     * @param tableName 表名, eg: gen_test_demo
     * @return
     */
    public static String tableNameConvertUpperCamel(String tableName) {
        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName.toLowerCase());
    }

    /**
     * 首字母转小写
     */
    public static String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0))) {
            return s;
        } else {
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }

    /**
     * 功能描述:
     * 〈获取表字段数据〉
     *
     * @Author: Simon
     * @Date: 2020/4/9 9:18
     */
    public static List<Column> listColumnByTableName(String tableName) {
        List<Column> list = new ArrayList<>();
        List<String> columnNames = DatabaseUtil.getColumnNames(tableName);
        List<String> columnTypes = DatabaseUtil.getColumnTypes(tableName);
        List<String> columnComments = DatabaseUtil.getColumnComments(tableName);
        List<Integer> columnLengths = DatabaseUtil.getColumnLengths(tableName);
        List<Integer> columnIsNullable = DatabaseUtil.getColumnIsNullable(tableName);

        for (int i = 0; i < columnNames.size(); i++) {
            Column column = new Column();
            column.setName(columnNames.get(i));
            column.setAnnotation(columnComments.get(i));
            column.setLength(columnLengths.get(i));
            column.setType(columnTypes.get(i));
            column.setJavaType(DatabaseUtil.toSqlToJava(columnTypes.get(i)));
            column.setIsNullable(columnIsNullable.get(i) == 0 ? "false" : "true");
            column.setFristMajusculeJavaType(tableNameConvertUpperCamel(columnNames.get(i)));
            column.setJavaName(toLowerCaseFirstOne(tableNameConvertUpperCamel(columnNames.get(i))));
            list.add(column);
        }
        return list;
    }

}
